<template>
  <!-- <div ref="testDiv" class="macBox" @mousedown="handleMouseDown">sss</div> -->

  <div class="Mycanvas" id="editor">
    <component
      v-for="(item, index) in componentDate"
      :is="item.component"
      :style="getShapeStyle(item.style)"
      @mousedown="handleMouseDown($event, index)"
      ref="shape"
      class="macBox"
    >
      <!-- 旋转 -->
      <div
        class="refresh"
        @mousedown="handleRotate($event, item.style, shape)"
      ></div>
      <!-- 八个顶点  -->
      <div
        class="shape-point"
        v-for="pointItem in pointList"
        :style="getPointStyle(pointItem, item.style)"
        @mousedown="handleMouseDownPoint($event, item.style, pointItem)"
    /></component>
  </div>
</template>
<script lang="ts" setup>
import Vimage from "@/components/Vimage/index.vue";
import { CSSProperties, defineComponent, ref } from "vue";
import { calculateComponentPositionAndSize } from "./dot/calculateComponentPositonAndSize";
import { ComponentDataType, cssDataType } from "./dot/PointType";

const testDiv = ref<any>(null);
const startTop = ref<number>(0);
const startLeft = ref<number>(0);

const pointList = ["lt", "t", "rt", "r", "rb", "b", "lb", "l"];
const getPointStyle = (point: any, defaultStyle: any) => {
  const { width, height } = defaultStyle;
  const hasT = /t/.test(point);
  const hasB = /b/.test(point);
  const hasL = /l/.test(point);
  const hasR = /r/.test(point);
  let newLeft = 0;
  let newTop = 0;

  // 四个角的点
  if (point.length === 2) {
    newLeft = hasL ? 0 : width;
    newTop = hasT ? 0 : height;
  } else {
    // 上下两点的点，宽度居中
    if (hasT || hasB) {
      newLeft = width / 2;
      newTop = hasT ? 0 : height;
    }

    // 左右两边的点，高度居中
    if (hasL || hasR) {
      newLeft = hasL ? 0 : width;
      newTop = Math.floor(height / 2);
    }
  }

  const style = {
    marginLeft: hasR ? "-10px" : "-10px",
    marginTop: "-10px",
    left: `${newLeft}px`,
    top: `${newTop}px`,
    cursor: "point",
  };
  return style;
};

const componentDate = ref<Array<ComponentDataType>>([
  {
    component: "div",
    style: {
      top: 200,
      left: 200,
      width: 200,
      height: 200,
      rotate: 0,
      fontSize: "",
      fontWeight: "",
      lineHeight: "",
      letterSpacing: "",
      textAlign: "",
      color: "",
    },
  },
]);

// 组件样式
const getShapeStyle = (style: any) => {
  const result: { [x: string]: string | number } = {
    width: "",
    height: "",
    top: "",
    left: "",
    rotate: "",
    borderRadius: "",
    zIndex: 0,
  };
  ["width", "height", "top", "left", "rotate", "borderRadius"].forEach(
    (attr) => {
      if (attr === "rotate") {
        result.transform = "rotate(" + style[attr] + "deg)";
      }
      if (attr === "zIndex") {
        result[attr] = style[attr];
      } else {
        result[attr] = style[attr] + "px";
      }
    }
  );
  return result;
};

// console.log("testDiv :>> ", testDiv.style);
const handleMouseDown = (e: MouseEvent, index: number) => {
  console.log("eMouseEvent :>> ", index);
  e.stopPropagation();
  //   console.log("testDiv :>> ", testDiv.value.style);
  console.log("e :>> ", index);
  const startY = e.clientY - +componentDate.value[index].style.top;
  const startX = e.clientX - +componentDate.value[index].style.left;
  // 如果直接修改属性，值的类型会变为字符串，所以要转为数值型
  //   const startTop = 0;
  //   const startLeft = 0;

  const move = (moveEvent: MouseEvent) => {
    const currX = moveEvent.clientX;
    const currY = moveEvent.clientY;
    console.log("?? :>> ", currX + " " + currY);
    // testDiv.value.style.left = currX - startX + "px";
    // testDiv.value.style.top = currY - startY + "px";

    // testDiv.value.style.left = currX - startX - startLeft.value + "px";
    // testDiv.value.style.top = currY - startY - startTop.value + "px";

    componentDate.value[index].style.left = currX - startX;
    componentDate.value[index].style.top = currY - startY;
    console.log("?? :>> ", componentDate.value[index].style);
    // // 修改当前组件样式
    // this.$store.commit("setShapeStyle", pos);
  };

  const up = (moveEvent: MouseEvent) => {
    // startTop.value = moveEvent.clientY - startY;
    // startLeft.value = moveEvent.clientX - startX;
    // console.log("moveEvent.clientX - startY; :>> ", moveEvent.clientX - startY);
    // console.log(
    //   " moveEvent.clientY - startX; :>> ",
    //   moveEvent.clientY - startX
    // );
    document.removeEventListener("mousemove", move);
    document.removeEventListener("mouseup", up);
  };

  document.addEventListener("mousemove", move);
  document.addEventListener("mouseup", up);
};

const handleMouseDownPoint = (
  event: MouseEvent,
  defaultStyle: cssDataType,
  pointSate: string
) => {
  event.stopPropagation();
  event.preventDefault();
  //得到组件宽高比
  const proportion = +defaultStyle.width / +defaultStyle.height;
  //获得组件中心点
  const center = {
    x: +defaultStyle.left + +defaultStyle.width / 2,
    y: +defaultStyle.top + +defaultStyle.height / 2,
  };
  //获得画布信息
  const contentCanvas = document
    .querySelector("#editor")
    ?.getBoundingClientRect();
  //获得point和实际拖动的差
  const pointRect = (event.target as HTMLElement).getBoundingClientRect();
  //获得点击点对于画布中心的坐标
  const curPoint = {
    x: Math.round(
      pointRect.left -
        contentCanvas!.left +
        (event.target as HTMLElement).offsetWidth / 2
    ),
    y: Math.round(
      pointRect.top -
        contentCanvas!.top +
        (event.target as HTMLElement).offsetHeight / 2
    ),
  };
  // 获得对称的焦点
  const symmetricPoint = {
    x: center.x - (curPoint.x - center.x),
    y: center.y - (curPoint.y - center.y),
  };

  let isFirst = true;
  //第一次不移动的
  const move = (moveEvent: MouseEvent) => {
    if (isFirst) {
      isFirst = false;
      return;
    }

    const curPosition = {
      x: moveEvent.clientX - contentCanvas!.left,
      y: moveEvent.clientY - contentCanvas!.top,
    };

    calculateComponentPositionAndSize(
      pointSate,
      defaultStyle,
      curPosition,
      proportion,
      false,
      {
        center,
        curPoint,
        symmetricPoint,
      }
    );
  };

  const up = () => {
    document.removeEventListener("mousemove", move);
    document.removeEventListener("mouseup", up);
  };

  document.addEventListener("mousemove", move);
  document.addEventListener("mouseup", up);
};
const handleRotate = (
  event: MouseEvent,
  defaultStyle: cssDataType,
  shape: Element
) => {
  event.stopPropagation();
  event.preventDefault();
  //初始坐标
  const position = defaultStyle;
  const startY = event.clientY;
  const startX = event.clientX;
  const startRotate = +position.rotate;
  // 元素中心点
  const rect = shape.getBoundingClientRect();
  const centerX = rect.left + rect.width / 2;
  const centerY = rect.top + rect.height / 2;

  //转之前
  const rotateDegreeBefore =
    Math.atan2(startY - centerY, startX - centerX) / (Math.PI / 180);
  const move = (mouseEvent: MouseEvent) => {
    const curX = mouseEvent.clientX;
    const curY = mouseEvent.clientY;

    // 旋转后弧度
    const rotateDegreeAfter =
      Math.atan2(curY - centerY, curX - centerX) / (Math.PI / 180);

    // 旋转后角度
    let rotate = startRotate + rotateDegreeAfter - rotateDegreeBefore;
    defaultStyle.rotate = rotate;
  };

  const up = (mouseEvent: MouseEvent) => {
    document.removeEventListener("mousemove", move);
    document.removeEventListener("mouseup", up);
  };
  document.addEventListener("mousemove", move);
  document.addEventListener("mouseup", up);
};

const shape = ref<any>(null);
</script>
<style lang="scss">
.macBox {
  position: absolute;
  background-color: aqua;
  width: 150px;
  height: 100px;
  border: 1px solid #000;
  border-radius: 5px;
  cursor: move;
}

.shape-point {
  width: 20px;
  height: 20px;
  position: absolute;
  background-color: #fdfdfd;
  top: -10px;
  left: -10px;
  border-radius: 50%;
  border: 1px solid;
  cursor: pointer;
}

.refresh {
  position: absolute;
  cursor: grab;
  border: 1px solid #000;
  background-color: #409eff;
  border-radius: 50%;
  font-size: 24px;
  font-weight: 600;
  top: -50px;
  left: 50%;
  transform: translateX(-50%);
  width: 25px;
  height: 25px;
}

.Mycanvas {
  background-color: #eaeaea;
  height: 800px;
  width: 1000px;
  margin: 0 auto;
  position: relative;
}
</style>
